using System;
using System.Collections.Generic;
using System.Text;

using XNAF = Microsoft.Xna.Framework;

namespace XGAE.Framework.Extensions
{
    /// <summary>
    /// 3D euler angle class with the basic operations required.
    /// </summary>
    public class Angles
    {
        private float _pitch, _yaw, _roll;

        public float Pitch
        {
            get { return this._pitch; }
            set { this._pitch = value; }
        }

        public float Yaw
        {
            get { return this._yaw; }
            set { this._yaw = value; }
        }

        public float Roll
        {
            get { return this._roll; }
            set { this._roll = value; }
        }

        public Angles(float pitch, float yaw, float roll)
        {
            this._pitch = pitch;
            this._yaw = yaw;
            this._roll = roll;
        }

        public Angles(Angles a)
        {
            this._pitch = a.Pitch;
            this._yaw = a.Yaw;
            this._roll = a.Roll;
        }

        public Angles(float a)
        {
            this._pitch = a;
            this._yaw = a;
            this._roll = a;
        }

        public Angles(SpheriCoord s)
        {
            this._pitch = s.Pitch;
            this._yaw = s.Yaw;
            this._roll = 0.0f;
        }

        public Angles() { }

        public XNAF.Vector3 AsVector()
        {
            float ay = -_yaw * (float)(XNAF.MathHelper.Pi / 180.0f),
                    sy = (float)Math.Sin(ay),
                    cy = (float)Math.Cos(ay),
                    ap = _pitch * (float)(XNAF.MathHelper.Pi / 180.0f),
                    sp = (float)Math.Sin(ap),
                    cp = (float)Math.Cos(ap);

            return new XNAF.Vector3( cp*cy, cp*sy, -sp );
        }

        public void Clear(/*float f*/)
	    {
            float f = 0.0f;
            /*if(f==null)
                f = 0.0f;*/
		    _pitch = f;
		    _yaw = f;
		    _roll = f;
	    }

        public void Set( Angles a )
	    {
		    _pitch = a.Pitch;
		    _yaw = a.Yaw;
		    _roll = a.Roll;
	    }

        /// <summary>
        /// Place of operator+=
        /// </summary>
        /// <param name="a"></param>
        public void Incriment(Angles a)
        {
            _pitch += a.Pitch;
		    _yaw += a.Yaw;
		    _roll += a.Roll;
        }

	    public static Angles Minus( Angles a1, Angles a2 )
	    {
            return new Angles( a1.Pitch - a2.Pitch, a1.Yaw - a2.Yaw, a1.Roll - a2.Roll );
	    }

        public static Angles Plus(Angles a1, Angles a2)
	    {
            return new Angles(a1.Pitch + a2.Pitch, a1.Yaw + a2.Yaw, a1.Roll + a2.Roll);
	    }


        public float this[int i]
        {
            get
            {
                switch (i)
                {
                    case 0:
                        return this._pitch;
                        break;
                    case 1:
                        return this._yaw;
                        break;
                    case 2:
                        return this._roll;
                        break;
                    default:
                        throw new Exception("Bad index!");
                        break;
                }
            }
            set
            {
                switch (i)
                {
                    case 0:
                        this._pitch = value;
                        break;
                    case 1:
                        this._yaw = value;
                        break;
                    case 2:
                        this._roll = value;
                        break;
                    default:
                        throw new Exception("Bad index!");
                        break;
                }
            }
        }
    }

    /// <summary>
    /// 3D spherical coordinate class with the basic operations required.
    /// </summary>
    public class SpheriCoord
    {

        private float _pitch, _yaw;
        private float _dist = 1.0f;

        public float Pitch
        {
            get { return this._pitch; }
            set { this._pitch = value; }
        }

        public float Yaw
        {
            get { return this._yaw; }
            set { this._yaw = value; }
        }

        public float Dist
        {
            get { return this._dist; }
            set { this._dist = value; }
        }
	
	    public SpheriCoord( float pitch, float yaw, float dist) 
	    {
            _pitch = pitch;
	        _yaw = yaw;
	        _dist = dist;
	    }

	    public SpheriCoord( SpheriCoord s ) 
	    {
            _pitch = s.Pitch;
	        _yaw = s.Yaw;
	        _dist = s.Dist;
	    }

	    public SpheriCoord()
	    {
	    }

	    public XNAF.Vector3 AsVector()
        {
	        return new Angles(_pitch, _yaw, 0.0f).AsVector() * _dist;
        }

        public void Set(Angles a)
        {
            _pitch = a.Pitch;
            _yaw = a.Yaw;
        }
    }
}

